package com.example.demo.service.impl;

import com.example.demo.model.Category;
import com.example.demo.model.TextDocument;
import com.example.demo.model.User;
import com.example.demo.repository.CategoryRepository;
import com.example.demo.repository.TextDocumentRepository;
import com.example.demo.service.PermissionService;
import com.example.demo.service.TextDocumentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class TextDocumentServiceImpl implements TextDocumentService {

    private final TextDocumentRepository textDocumentRepository;
    private final CategoryRepository categoryRepository;
    private final PermissionService permissionService;

    @Autowired
    public TextDocumentServiceImpl(
            TextDocumentRepository textDocumentRepository, 
            CategoryRepository categoryRepository,
            PermissionService permissionService) {
        this.textDocumentRepository = textDocumentRepository;
        this.categoryRepository = categoryRepository;
        this.permissionService = permissionService;
    }

    @Override
    @Cacheable(value = "allDocuments", key = "#root.methodName + '_' + #root.target")
    public List<TextDocument> getAllDocuments() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        
        // 未登录用户只能看到公开文档
        if (auth == null || auth.getPrincipal() == null || "anonymousUser".equals(auth.getPrincipal())) {
            return textDocumentRepository.findByIsPublicTrueOrderByCreatedAtDesc();
        }
        
        User currentUser = (User) auth.getPrincipal();
        
        // 管理员可以看到所有文档
        if (currentUser.isAdmin() || permissionService.hasPermission(currentUser, "VIEW_ALL_DOCUMENTS")) {
            return textDocumentRepository.findAllByOrderByCreatedAtDesc();
        } else {
            // 普通用户只能看到自己的文档和公开文档
            return textDocumentRepository.findByIsPublicTrueOrAuthorOrderByCreatedAtDesc(currentUser.getUsername());
        }
    }

    @Override
    @Cacheable(value = "featuredDocuments", key = "#root.methodName + '_' + #root.target")
    public List<TextDocument> getFeaturedDocuments() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        
        // 未登录用户只能看到公开的精选文档
        if (auth == null || auth.getPrincipal() == null || "anonymousUser".equals(auth.getPrincipal())) {
            return textDocumentRepository.findByIsPublicTrueAndFeaturedTrueOrderByCreatedAtDesc();
        }
        
        User currentUser = (User) auth.getPrincipal();
        
        // 管理员可以看到所有精选文档
        if (currentUser.isAdmin() || permissionService.hasPermission(currentUser, "VIEW_ALL_DOCUMENTS")) {
            return textDocumentRepository.findByFeaturedTrueOrderByCreatedAtDesc();
        } else {
            // 普通用户只能看到公开的精选文档或自己的精选文档
            return textDocumentRepository.findByFeaturedTrueAndIsPublicTrueOrFeaturedTrueAndAuthorOrderByCreatedAtDesc(currentUser.getUsername());
        }
    }

    @Override
    @Cacheable(value = "documentsByCategory", key = "#categoryId")
    public List<TextDocument> getDocumentsByCategory(Long categoryId) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        
        // 未登录用户只能看到公开文档
        if (auth == null || auth.getPrincipal() == null || "anonymousUser".equals(auth.getPrincipal())) {
            return textDocumentRepository.findByCategoryIdAndIsPublicTrueOrderByCreatedAtDesc(categoryId);
        }
        
        User currentUser = (User) auth.getPrincipal();
        
        // 管理员可以看到分类下的所有文档
        if (currentUser.isAdmin() || permissionService.hasPermission(currentUser, "VIEW_ALL_DOCUMENTS")) {
            return textDocumentRepository.findByCategoryIdOrderByCreatedAtDesc(categoryId);
        } else {
            // 普通用户只能看到分类下的公开文档或自己的文档
            return textDocumentRepository.findByCategoryIdAndIsPublicTrueOrCategoryIdAndAuthorOrderByCreatedAtDesc(categoryId, currentUser.getUsername());
        }
    }

    @Override
    @Cacheable(value = "documentsById", key = "#id")
    public TextDocument getDocumentById(Long id) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        
        // 未登录用户只能看到公开文档
        if (auth == null || auth.getPrincipal() == null || "anonymousUser".equals(auth.getPrincipal())) {
            TextDocument document = textDocumentRepository.findByIdAndIsPublicTrue(id);
            if (document == null) {
                throw new AccessDeniedException("您需要登录才能查看此文档");
            }
            return document;
        }
        
        User currentUser = (User) auth.getPrincipal();
        
        // 管理员可以查看任何文档
        if (currentUser.isAdmin() || permissionService.hasPermission(currentUser, "VIEW_ALL_DOCUMENTS")) {
            return textDocumentRepository.findById(id).orElse(null);
        } else {
            // 普通用户只能查看公开文档或自己的文档
            TextDocument document = textDocumentRepository.findByIdAndIsPublicTrueOrAuthor(id, currentUser.getUsername());
            if (document == null) {
                throw new AccessDeniedException("您没有权限查看此文档");
            }
            return document;
        }
    }

    @Override
    @CacheEvict(value = {"allDocuments", "featuredDocuments", "documentsByCategory", "documentsById"}, allEntries = true)
    public TextDocument saveDocument(TextDocument document) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User currentUser = (User) auth.getPrincipal();
        
        // 如果是新文档
        if (document.getId() == null) {
            // 检查创建文档权限
            if (currentUser.isAdmin()) {
                if (!permissionService.hasPermission(currentUser, "ADMIN_CREATE_DOCUMENT")) {
                    throw new AccessDeniedException("管理员没有创建文档的权限");
                }
            } else {
                if (!permissionService.hasPermission(currentUser, "USER_CREATE_DOCUMENT")) {
                    throw new AccessDeniedException("用户没有创建文档的权限");
                }
            }
            document.setAuthor(currentUser.getUsername());
        } else {
            // 如果是编辑现有文档
            TextDocument existingDoc = textDocumentRepository.findById(document.getId()).orElse(null);
            if (existingDoc == null) {
                throw new IllegalArgumentException("文档不存在");
            }
            
            boolean canEdit = currentUser.isAdmin() || 
                    permissionService.hasPermission(currentUser, "EDIT_ALL_DOCUMENTS") ||
                    (existingDoc.getAuthor().equals(currentUser.getUsername()) && 
                     permissionService.hasPermission(currentUser, "EDIT_OWN_DOCUMENTS"));
                     
            if (!canEdit) {
                throw new AccessDeniedException("您没有权限编辑此文档");
            }
        }
        
        return textDocumentRepository.save(document);
    }

    @Override
    @CacheEvict(value = {"allDocuments", "featuredDocuments", "documentsByCategory", "documentsById"}, allEntries = true)
    public void deleteDocument(Long id) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User currentUser = (User) auth.getPrincipal();
        
        TextDocument document = textDocumentRepository.findById(id).orElse(null);
        if (document == null) {
            return;
        }
        
        boolean canDelete = currentUser.isAdmin() || 
                permissionService.hasPermission(currentUser, "DELETE_ALL_DOCUMENTS") ||
                (document.getAuthor().equals(currentUser.getUsername()) && 
                 permissionService.hasPermission(currentUser, "DELETE_OWN_DOCUMENTS"));
                 
        if (!canDelete) {
            throw new AccessDeniedException("您没有权限删除此文档");
        }
        
        textDocumentRepository.deleteById(id);
    }

    @Override
    @CacheEvict(value = {"allDocuments", "featuredDocuments"}, allEntries = true)
    public void toggleFeatured(Long id) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User currentUser = (User) auth.getPrincipal();
        
        // 只有管理员可以设置精选文档
        if (!currentUser.isAdmin()) {
            throw new AccessDeniedException("只有管理员可以设置精选文档");
        }
        
        Optional<TextDocument> documentOpt = textDocumentRepository.findById(id);
        if (documentOpt.isPresent()) {
            TextDocument document = documentOpt.get();
            document.setFeatured(!document.isFeatured());
            textDocumentRepository.save(document);
        }
    }

    @Override
    @CacheEvict(value = {"allDocuments", "documentsByCategory"}, allEntries = true)
    public TextDocument updateDocumentCategory(Long documentId, Long categoryId) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User currentUser = (User) auth.getPrincipal();
        
        Optional<TextDocument> documentOpt = textDocumentRepository.findById(documentId);
        Optional<Category> categoryOpt = categoryRepository.findById(categoryId);
        
        if (documentOpt.isPresent() && categoryOpt.isPresent()) {
            TextDocument document = documentOpt.get();
            
            boolean canEdit = currentUser.isAdmin() || 
                    permissionService.hasPermission(currentUser, "EDIT_ALL_DOCUMENTS") ||
                    (document.getAuthor().equals(currentUser.getUsername()) && 
                     permissionService.hasPermission(currentUser, "EDIT_OWN_DOCUMENTS"));
                     
            if (!canEdit) {
                throw new AccessDeniedException("您没有权限修改此文档的分类");
            }
            
            document.setCategory(categoryOpt.get());
            return textDocumentRepository.save(document);
        }
        return null;
    }
    
    @Override
    public long countAllDocuments() {
        return textDocumentRepository.count();
    }

    @Override
    public long countTodayDocuments() {
        LocalDate today = LocalDate.now();
        LocalDateTime startOfDay = today.atStartOfDay();
        LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
        return textDocumentRepository.countByCreatedAtBetween(startOfDay, endOfDay);
    }
} 